﻿using System;
using System.Threading.Tasks;
using AsyncTestingDemo.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace AsyncTestingDemo.Tests
{
    internal class TaskHelpers
    {
        public static Task<T> CreatePseudoTask<T>(T result)
        {
            TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
            tcs.SetResult(result);
            return tcs.Task;
        }
    }

    [TestClass]
    public class AsyncStubsDemo
    {
        // Returning a Task from a Stub
        [TestMethod]
        public async Task TestWithRealRunningTask()
        {
            // Arrange
            var stub = new StubIDoStuff
            {
                LongRunningOperation = () => Task<string>.Run(() => "Hello there!")
            };
            var sut = new SystemUnderTest(stub);

            // Act
            var result = await sut.DoSomething();

            // Assert
            Assert.AreEqual("Interface said 'Hello there!'", result);
        }

        // In .NET 4.0 you can use TaskCompletionSource to avoid
        // creating a scheduled task deleate (background thread)
        [TestMethod]
        public async Task TestWithHandCodedTCS()
        {
            // Arrange
            var stub = new StubIDoStuff
            {
                LongRunningOperation = () => {
                    var tcs = new TaskCompletionSource<string>();
                    tcs.SetResult("Hello there!");
                    return tcs.Task;
                }
            };
            var sut = new SystemUnderTest(stub);

            // Act
            var result = await sut.DoSomething();

            // Assert
            Assert.AreEqual("Interface said 'Hello there!'", result);
            // Arrange
        }

        // In .NET 4.0 you can use TaskCompletionSource to avoid
        // creating a scheduled task deleate (background thread)
        [TestMethod]
        public async Task TestWithPseudoTask()
        {
            // Arrange
            var stub = new StubIDoStuff
            {
                LongRunningOperation = () => TaskHelpers.CreatePseudoTask<string>("Hello there!")
            };
            var sut = new SystemUnderTest(stub);

            // Act
            var result = await sut.DoSomething();

            // Assert
            Assert.AreEqual("Interface said 'Hello there!'", result);
        }

        // Simplified version using .NET 4.5 Task.FromResult
        [TestMethod]
        public async Task TestWithFromResultHelper()
        {
            // Arrange
            var stub = new StubIDoStuff
            {
                LongRunningOperation = () => Task.FromResult("Hello there!")
            };
            var sut = new SystemUnderTest(stub);

            // Act
            var result = await sut.DoSomething();

            // Assert
            Assert.AreEqual("Interface said 'Hello there!'", result);
        }
    }
}
